import 'dart:async';
import 'dart:convert';

import 'package:cloudapp/common/common.dart';
import 'package:cloudapp/esdk/db.dart';
import 'package:cloudapp/esdk/esync.dart';
import 'package:cloudapp/esdk/model/server_info.dart';
import 'package:cloudapp/esdk/model/session_info.dart';
import 'package:cloudapp/model/global_info.dart';
import 'package:cloudapp/pages/base.dart';
import 'package:cloudapp/pages/cloud_album_page.dart';
import 'package:cloudapp/pages/qrcode_scan.dart';
import 'package:cloudapp/pages/servers_page.dart';
import 'package:flutter/material.dart';

class UserLoginPage extends StatefulWidget {
  static const pageName = "/login";

  @override
  State<StatefulWidget> createState() {
    return _UserLoginPage();
  }
}

// 用户登录界面
class _UserLoginPage extends BaseState<UserLoginPage> {
  final _userCtl = TextEditingController();
  final _pwdCtl = TextEditingController();
  final _servers = <ServerInfo>[];
  var _curServer = 0;

  @override
  void initState() {
    super.initState();
    Future.delayed(Duration.zero, loadServerLists);
  }

  @override
  Widget build(BuildContext context) {
    _userCtl.text = "esync";
    _pwdCtl.text = "123456";

    return Scaffold(
      appBar: AppBar(
        title: Text('LoginPage'),
      ),
      body: Container(
        margin: const EdgeInsets.fromLTRB(20, 40, 20, 0),
        child: Form(
            child: Column(
              children: <Widget>[
                TextFormField(
                  controller: _userCtl,
                  decoration: InputDecoration(
                      labelText: '用户名',
                      helperText: '输入用户名'
                  ),
                ),
                TextFormField(
                  controller: _pwdCtl,
                  decoration: InputDecoration(
                      labelText: '密码',
                      helperText: '请输入密码'
                  ),
                ),
                DropdownButton<int>(
                  value: _curServer,
                  icon: Icon(Icons.arrow_drop_down),
                  iconSize: 20,
                  elevation: 10,
                  underline: Container(
                    height: 2,
                    color: Colors.deepPurpleAccent,
                  ),
                  onChanged: (v) {
                    setState(() {
                      _curServer = v;
                    });
                  },
                  items: _servers.map<DropdownMenuItem<int>>((serverItem) {
                    return DropdownMenuItem<int>(
                      value: serverItem.id,
                      child: Text('服务器 ${serverItem.inIpAddr}'),
                    );
                  }).toList(),
                ),
                RaisedButton(
                  child: Text('Go'),
                  onPressed: loginClicked,
                ),
                RaisedButton(
                  child: Text('服务器发现'),
                  onPressed: goFindServer,
                ),
                RaisedButton(
                  child: Text('PageTest'),
                  onPressed: goPageTest,
                )
              ],
            )
        ),
      ),
    );
  }

  void loginClicked() async {
    final userName = _userCtl.text;
    final pwd = _pwdCtl.text;
    // 先获取对应服务器的地址
    final pos = _servers.indexWhere((element) => element.id == _curServer);
    if(pos == -1) {
      showToast('请选择服务器');
      return;
    }
    final sInfo = _servers[pos];

    // 再设置 网络请求的 base
    ESync.i().setServerHost(sInfo.inIpAddr);

    // 登录验证
    var rsp = await loading(() async {
      return await ESync.i().userLogin(userName, pwd);
    });
    print(rsp);
    // 1. 保存会话信息
    final now = DateTime.now();
    final session = SessionInfo(
      id: null,
      userId: rsp.userId,
      serverId: sInfo.id,
      lastUsed: now.millisecondsSinceEpoch~/1000,
      loginResponse: jsonEncode(rsp.toJson()),
    );
    final sessionId = await DbStorage.i().saveSession(sInfo.id, session);
    // 2. 设置全局 sessionId 值
    GlobalInfo.i().setSessionId(sessionId);
    // 3. 设置网络请求 token
    ESync.i().setToken(rsp.userId, rsp.accessToken);
    // 4. 跳转到主界面
    await Navigator.pushNamedAndRemoveUntil(context, CloudAlbumPage.pageName, (_) => false);
  }

  /// 先加载所有服务器，再二维码扫描，根据结果，新增与否
  Future<void> goFindServer() async {
    final servers = await DbStorage.i().loadAllServers();
    final serverMaps = Map<String, ServerInfo>();
    servers.forEach((element) => serverMaps[element.serverHash] = element);

    var value = await Navigator.pushNamed(context, QRCodeScan.pageName);
    var dstAddr = value as String;
    if(dstAddr == null || dstAddr.isEmpty) {
      print('get addr empty!');
      return;
    }

    ESync.i().setServerHost(dstAddr);
    // 请求服务器查询 hash 值
    final sInfo = await loading(() async {
      return await ESync.i().getServerInfo();
    });
    if(sInfo == null) {
      return;
    }

    // 服务器可能更换了IP地址，但 hash 值未更换
    if(serverMaps.containsKey(sInfo.serverId)) {
      var server = serverMaps[sInfo.serverId];
      if(server.inIpAddr == dstAddr) {
        showToast('您扫描的服务器已在列表里，请从列表中选择');
        return;
      }

      // serverHash 在表中，但服务器IP地址变更 1. 数据库更改服务器IP 2. _servers 值变更
      await DbStorage.i().modServerAddr(server.id, dstAddr);
      var pos = _servers.indexWhere((element) => element.serverHash == sInfo.serverId);
      if(pos == -1) {
        showToast('逻辑错误!');
        return;
      }
      var oldServer = _servers[pos];
      var nServer = ServerInfo(
        id: oldServer.id,
        inIpAddr: dstAddr,
        outIpAddr: oldServer.outIpAddr,
        serverHash: oldServer.serverHash,
        port: oldServer.port,
      );
      setState(() {
        _servers.removeAt(pos);
        _servers.add(nServer);
        _curServer = nServer.id;
      });
      return;
    }

    // 新增入库
    final sDbItem = ServerInfo(
      id: null,
      inIpAddr: dstAddr,
      outIpAddr: null,
      serverHash: sInfo.serverId,
      port: 18083,
    );
    final sId = await DbStorage.i().addServer(sDbItem);
    sDbItem.id = sId;

    // ui 更新下拉列表框
    setState(() {
      _servers.add(sDbItem);
      _curServer = sDbItem.id;
    });
    showToast('服务器IP: $dstAddr 新增成功');
  }

  Future<void> loadServerLists() async {
    final servers = await DbStorage.i().loadAllServers();
    setState(() {
      _servers.clear();
      for(var item in servers) {
        _servers.add(item);
        if(_servers.length > 0) {
          _curServer = _servers[0].id;
        }
      }
    });
  }

  void goPageTest() {
    Navigator.pushNamed(context, ServersPage.pageName);
  }
}
